package com.thinvent.recommend.common.util;

import javax.servlet.http.HttpServletRequest;

/**
 * tips：
 * 1、确保代理服务传递头部
 * 如果你用 Nginx 做反向代理，需要在配置里加上：
 * proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 * proxy_set_header Host $host;
 *
 * 2、IPv6 环回地址
 * 本地测试时常见 0:0:0:0:0:0:0:1，可在返回前统一替换成 127.0.0.1，比如：
 * if ("0:0:0:0:0:0:0:1".equals(ip)) {
 *     ip = "127.0.0.1";
 * }
 *
 * 3、安全考虑
 * HTTP 头可以伪造，切勿仅依赖头部做权限校验；获取 IP 更多是用来做日志、限流或地理位置分析。
 */
public class IpUtils {

    /**
     * 获取客户端真实 IP 地址。优先从 X-Forwarded-For、Proxy-Client-IP、WL-Proxy-Client-IP 等头部读取，
     * 再回退到 request.getRemoteAddr()，并只保留逗号分隔串中的第一个 IP。
     */
    public static String getClientIp(HttpServletRequest request) {
        String ip = null;
        // 常见代理头，X-Forwarded-For 中可能会有多个 IP，第一位是真实客户端
        String[] headers = {
                "X-Forwarded-For",
                "Proxy-Client-IP",
                "WL-Proxy-Client-IP",
                "HTTP_CLIENT_IP",
                "HTTP_X_FORWARDED_FOR"
        };
        for (String header : headers) {
            String headerIp = request.getHeader(header);
            if (headerIp != null && headerIp.length() != 0 && !"unknown".equalsIgnoreCase(headerIp)) {
                ip = headerIp;
                break;
            }
        }
        // 回退到请求源
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 如果通过多个代理，X-Forwarded-For 值可能是 "client1, proxy1, proxy2"，取第一个即是真实客户端
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        if ("0:0:0:0:0:0:0:1".equals(ip)) {
            ip = "127.0.0.1";
        }
        return ip;
    }
}

